#pragma once

/* brk has been deprecated on macos, so this mlayer uses mmap instead of brk */

/* 所有层要求按照对齐方式对齐, 若非对齐内存则是上层分配的 */
#include <metalc/base/mlayer.h>

#include <metalc/mlos/mmap/unix_mmap.h>
// 唯一性
#if (WORD_WIDTH == 64)
	#define HEAPSTART_OFFST	 (SIZE_1G)
#elif (WORD_WIDTH == 32)
	#define HEAPSTART_OFFST	 (SIZE_256M)
#endif

/* 这个必须持有锁才能访问 */
typedef struct brkheap
{
	void *start_heap_ptr;
	void *cur_heap_ptr;
} brkheap_t;

/* 全局唯一 */

DEF_MLOS(brkheap, 0)

static inline void brkheap_init(brkheap_t *l){
	l->start_heap_ptr = os_get_heapstart();
	INFO("brkheap start at %p\n", l->start_heap_ptr);
	l->cur_heap_ptr = l->start_heap_ptr;
}

SAI brkheap_t *brkheap_get(){
	static brkheap_t glb_brkheap;
	return &glb_brkheap;
}
SAI void brkheap_pinit(const mlfunc_t * cont){ 
	PARAM_USED(cont);
	brkheap_t *hp = brkheap_get();
	if (hp->cur_heap_ptr == NULL_PTR) brkheap_init(hp);
}

SAI void brkheap_tinit(const mlfunc_t * cont){
	PARAM_USED(cont);
}

SAI void *brkheap_alloc(mreq_t *req, const mlfunc_t * cont){
	PARAM_USED(cont);
	brkheap_t *l = brkheap_get();
	
	void *ret = NULL;
	size_t size = req->size;
	size_t align = req->align;

	/* */
	// ASSERT(align && align >= PAGE_SIZE);
	/* 使用1G巨页 对齐? */
	size_t align_size = align_up(req->size, PAGE_SIZE);
	size_t align_mask = align - 1;

	do
	{
		/* 分配一个对齐的 */
		// word_t ocupied_ptr = faa((word_t *)&l->cur_heap_ptr, align_size);
		/* 不使用锁，默认由下层维护线程安全 */
		paddr_t ocupied_ptr = (paddr_t) l->cur_heap_ptr;
		l->cur_heap_ptr += align_size;

		/* 对齐到 */
		if (align && !is_aligned(ocupied_ptr, align)){
			align_size += align;
			paddr_t ori_ptr = ocupied_ptr;
			if (ocupied_ptr & align_mask){
				/* 未对齐 强行对齐 */
				ocupied_ptr = (ocupied_ptr + align_mask) & (~(align_mask));
				align_size -= (ocupied_ptr - ori_ptr);
			}
		}

		ret = os_commit((void *)ocupied_ptr, align_size);
		if (ret)
		{
			INFO("brkheap get %p, %lu\n", ret, align_size);
			req->size = align_size;
			req->ptr = ret;
			break;
		}
		else{
			fatal("ocupied ptr %lx, size %lu failed\n", ocupied_ptr, size);
		}
	} while (TRUE);
	req->ptr = ret;
	return ret;
}

SAI bool_t brkheap_free(mreq_t *req, const mlfunc_t * cont){
	PARAM_USED(cont);
	// 不用在查表
	// brkheap_t *l = brkheap_get();
	void *ptr = req->ptr;


	return os_decommit(ptr, req->size);
}

/* 系统层不管理对象大小, 仅用于内部使用 */
SAI size_t brkheap_sizeof(mreq_t *req, const mlfunc_t * cont){
	PARAM_USED(req, cont);
	/* 由下面的大内存申请层管理 */
	req->size = MSIZEOF_ERR;
	return MSIZEOF_ERR;
}

